import {
  AutoComplete,
  Button,
  Checkbox,
  Col,
  Form,
  Input,
  InputNumber,
  message,
  Modal,
  Popconfirm,
  Radio,
  Row,
  Select,
  Spin,
  TreeSelect,
  Space,
  Divider,
} from 'antd'
import { PlusOutlined } from '@ant-design/icons'
import React, { PureComponent } from 'react'
import _ from 'lodash'
import list2tree from 'list2tree'
import { ProTable, ProTableOptions } from '@/components'
import styles from './index.less'
import {
  getDictionaryList, saveModel, saveNewModel, treeThemes, saveTheme,
} from './api'
import { regExp } from '@/utils/regExp'

const getNavTreeDataFunc = list2tree({
  idKey: 'id',
  parentIdKey: 'pid',
  newKey: {
    key: 'id',
    value: 'id',
    title: 'themeName',
  },
})

const { Item } = Form
const { Option } = Select
const { TextArea } = Input

const nameReg = regExp.name(2, 32)

const EditableCell = ({
  editing,
  dataIndex,
  title,
  inputType,
  record,
  index,
  children,
  ...restProps
}) => {
  const inputNode = inputType && inputType(record)

  return (
    <td {...restProps}>
      {editing ? (
        inputNode
      ) : (
        children
      )}
    </td>
  )
}

export default class NewModelModal extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      loading: false,
      visible: false,
      treeData: [],
      columns: [
        {
          title: '字段名',
          dataIndex: 'name',
          width: '20%',
          key: 'name',
          editable: true,
          inputType: () => (
            <Form.Item
              name="name"
              style={{ margin: 0 }}
              rules={[
                {
                  required: true,
                  message: '请输入字段名',
                },
              ]}
            >
              <AutoComplete
                placeholder="请输入字段名"
                options={this.state.dictionaryOptions}
                filterOption={(inputValue, option) => option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1}
              />
            </Form.Item>
          ),
          render: (text, record) => (<div>{record.name}</div>),
        },
        {
          title: '字段描述',
          dataIndex: 'dsc',
          width: '20%',
          key: 'dsc',
          editable: true,
          inputType: () => (
            <Form.Item
              name="dsc"
              style={{ margin: 0 }}
            >
              <Input
                placeholder="请输入字段描述"
                autoComplete="off"
              />
            </Form.Item>
          ),
          render: (text, record) => (<span>{record.dsc}</span>),
        },
        {
          title: '字段类型',
          dataIndex: 'type',
          width: '20%',
          key: 'type',
          editable: true,
          inputType: () => (
            <Form.Item
              name="type"
              style={{ margin: 0 }}
              rules={[
                {
                  required: true,
                  message: '请输入字段类型',
                },
              ]}
            >
              <Select
                style={{ width: '100%' }}
                showSearch
                filterOption={(input, option) => option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                placeholder="请输入字段类型"
              >
                {
                  this.props.fieldTypes.map((item) => (
                    <Option value={item.name} key={item.name}>
                      {item.name}
                    </Option>
                  ))
                }
              </Select>
            </Form.Item>
          ),
          render: (text, record) => (<span>{record.type}</span>),
        },
        {
          title: '是否必填',
          dataIndex: 'isRequired',
          width: '13%',
          key: 'isRequired',
          editable: true,
          inputType: () => (
            <Form.Item
              name="isRequired"
              style={{ margin: 0 }}
              valuePropName="checked"
            >
              <Checkbox
                disabled={this.props.storageType === 'Hive' || this.state.tableType === 'VIEW'}
              />
            </Form.Item>
          ),
          render: (text, record) => (
            <Checkbox
              disabled
              checked={record.isRequired}
            />
          ),
        },
        {
          title: '是否分区',
          dataIndex: 'isPartition',
          width: '13%',
          key: 'isPartition',
          editable: true,
          inputType: () => (
            <Form.Item
              name="isPartition"
              style={{ margin: 0 }}
              valuePropName="checked"
            >
              <Checkbox
                disabled={this.props.storageType == 'TiDB' || this.props.storageType == 'PostgreSQL' || this.props.storageType === 'Sap' || this.state.modelId !== '' || this.state.tableType === 'VIEW'}
                onChange={(e) => {
                  if (e.target.checked) {
                    this.tableData.current.setFieldsValue({
                      type: 'string',
                    })
                  }
                }}
              />
            </Form.Item>
          ),
          render: (text, record) => (
            <Checkbox
              disabled
              checked={record.isPartition}
            />
          ),
        },
        {
          title: '操作',
          dataIndex: 'operation',
          width: '14%',
          key: 'operation',
          editable: true,
          inputType: (record) => (
            <ProTableOptions>
              <span onClick={this.onFieldSaveClick}>保存</span>
              {
                (!record.name || record.name === '') ? (
                  null
                ) : (
                  <span onClick={this.onFieldCancelClick}>取消</span>
                )
              }
            </ProTableOptions>
          ),
          render: (text, record, index) => (
            <ProTableOptions>
              {
                (this.state.modelId !== '' && record.isPartition) ? null : (
                  <>
                    {this.state.tableType === 'VIEW' ? '无' : <span onClick={() => this.onEditClick(record)}>编辑</span>}
                    {
                      this.state.modelId === '' && this.state.tableType !== 'VIEW' && (
                        <Popconfirm
                          title="你确定要删除这个字段吗？"
                          okText="确定"
                          cancelText="取消"
                          onConfirm={() => this.onDelClick(record)}
                        >
                          <span>
                            删除
                          </span>
                        </Popconfirm>
                      )
                    }
                  </>
                )
              }
            </ProTableOptions>
          ),
        },
      ],
      data: [],
      editKey: undefined,
      titleStr: '新建',
      modelId: '',
      showLifeCycleNum: false,
      dictionaryOptions: [],
    }

    this.form = React.createRef()
    this.formTheme = React.createRef()
    this.tableData = React.createRef()
  }

  componentDidMount() {
    getDictionaryList().then(
      (res) => {
        const arr = []
        res.map((item) => {
          arr.push({
            value: item.dictNameEn,
            label: `${item.dictNameEn}（${item.dictNameCn}）`,
          })
        })
        this.setState({ dictionaryOptions: arr })
      },
      (error) => {

      },
    )
  }

  handleData(data) {
    const newObj = {
      lifeCycle: data.lifeCycle,
      cnName: data.cnName,
      supportRtf: data.supportRtf,
      themeId: data.themeId,
      // dataSecretId: data.dataSecretId,
    }
    if (data.enName.indexOf('_') !== -1) {
      const enArr = data.enName.split('_')
      newObj.enName = {}
      newObj.enName.pre = `${enArr[0]}_`
      newObj.enName.sec = data.enName.slice(enArr[0].length + 1, data.enName.length)
    } else {
      newObj.enName = {}
      newObj.enName.pre = ''
      newObj.enName.sec = data.enName
    }

    if (data.lifeCycle !== 1 && data.lifeCycle !== 7 && data.lifeCycle !== 30 && data.lifeCycle !== -1) {
      newObj.lifeCycle = 'all'
      newObj.lifeCycleNum = data.lifeCycle
      this.setState({ showLifeCycleNum: true })
    } else {
      this.setState({ showLifeCycleNum: false })
    }
    if (data.schema) {
      newObj.schema = data.schema
    }
    const dataArr = data.fields.map((item, index) => ({
      dsc: item.fieldDesc,
      name: item.fieldName,
      type: item.fieldType,
      isPartition: item.isPartition,
      isRequired: item.required,
      key: index,
      recordType: 'edit',
    }))

    this.form.current.setFieldsValue(newObj)
    this.setState({ data: dataArr })
    return newObj
  }

  // 删除
  onDelClick(record) {
    const arr = []
    this.state.data.map((item) => {
      if (item.key !== record.key) {
        arr.push(item)
      }
    })
    arr.map((item, index) => {
      item.key = index
    })
    this.setState({
      data: arr,
    })
  }

  // 添加字段
  onAddClick = () => {
    if (this.state.editKey || this.state.editKey === 0) {
      message.warning('请先完成当前字段的编辑')
      return
    }
    const { data } = this.state
    // eslint-disable-next-line react/no-access-state-in-setstate
    const len = this.state.data.length
    data.push({
      name: undefined,
      dsc: undefined,
      type: undefined,
      isPartition: false,
      isRequired: false,
      key: len,
    })
    this.tableData.current.resetFields()
    this.setState({
      editKey: len,
      data: _.clone(data),
    })
  }

  // 保存字段修改
  onFieldSaveClick = () => {
    this.tableData.current.validateFields().then(values => {
      const { data, editKey } = this.state
      const dataObj = data.find((item) => item.key === editKey)
      // 如果修改字段类型弹出提示
      if (dataObj.recordType === 'edit' && dataObj.type !== values.type) {
        message.warning('数据类型变更可能会导致数据丢失，请谨慎操作')
      }
      const newObj = { ...dataObj }
      newObj.name = values.name
      newObj.dsc = values.dsc
      newObj.type = values.type
      newObj.isPartition = !!values.isPartition
      newObj.isRequired = !!values.isRequired
      const tempData = data.map((item) => {
        if (item.key === newObj.key) {
          return newObj
        }
        return item
      })
      this.setState({
        editKey: undefined,
        data: tempData,
      })
    })
  }

  // 取消字段修改
  onFieldCancelClick = () => {
    const { data } = this.state
    this.setState({
      editKey: undefined,
      data: _.clone(data),
    })
  }

  // 编辑按钮回调
  onEditClick = (record) => {
    if (this.state.editKey || this.state.editKey === 0) {
      message.warning('请先完成当前字段的编辑')
      return
    }
    this.tableData.current.setFieldsValue(record)
    this.setState({
      editKey: record.key,
    })
  }

  onConfirm = () => {
    if (this.state.editKey || this.state.editKey === 0) {
      message.warning('请先完成当前字段的编辑')
      return
    }
    if (this.state.data.length === 0) {
      message.warning('请至少配置一个字段')
      return
    }
    if (this.props.storageType === 'Hive') {
      let normalFieldNum = 0
      let partitionString = false
      this.state.data.map((item) => {
        if (!item.isPartition) normalFieldNum++
        if (item.isPartition && item.type !== 'string') partitionString = true
      })
      if (normalFieldNum === 0) {
        message.warning('请至少配置一个非分区字段')
        return
      }
      if (partitionString) {
        message.warning('分区字段必须是string类型')
        return
      }
    }
    this.form.current.validateFields().then(values => {
      this.setState({ loading: true })
      values.modelType = values.enName.pre.slice(0, values.enName.pre.length - 1)
      values.enName = values.enName.pre + values.enName.sec
      if (values.lifeCycle === 'all') {
        values.lifeCycle = values.lifeCycleNum
      }
      values.fields = this.state.data.map((item) => ({
        fieldDesc: item.dsc,
        fieldName: item.name,
        fieldType: item.type,
        isPartition: item.isPartition,
        required: item.isRequired,
      }))
      let postFun = saveNewModel
      let msgStr = '新建模型成功'
      if (this.state.modelId !== '') {
        postFun = saveModel
        values.modelId = this.state.modelId
        msgStr = '编辑模型成功'
      }
      postFun(values).then(
        (res) => {
          this.setState({
            visible: false,
            loading: false,
          }, () => {
            message.success(msgStr)
            this.props.closeCallBack && this.props.closeCallBack()
          })
        },
        (error) => {
          console.log(error)
          this.setState({ loading: false })
        },
      )
    })
  }

  // 编辑模型时打开
  // eslint-disable-next-line react/no-unused-class-component-methods
  onEditOpenModal(data) {
    this.setState({
      visible: true,
      titleStr: '编辑',
      modelId: data.id,
      tableType: data.tableType,
    }, () => {
      this.handleData(data)
    })
  }

  // getTypeOptions() {
  //   let arr
  //   if (this.props.storageType === 'PostgreSQL') {
  //     arr = pgTypeArr
  //   } else if (this.props.storageType === 'Hive') {
  //     arr = hiveTypeArr
  //   }
  //   return arr.map((item) => (
  //     <Option value={item} key={item}>
  //       {item}
  //     </Option>
  //   ))
  // }

  closeModal = () => {
    this.setState({
      visible: false,
      editKey: undefined,
    })
  }

  // 新建模型时打开
  // eslint-disable-next-line react/no-unused-class-component-methods
  openModal = (selectedKeys, pid) => {
    this.setState({
      visible: true,
      titleStr: '新建',
      modelId: '',
      data: [],
      showLifeCycleNum: false,
    }, () => {
      this.form.current && this.form.current.resetFields()
      if (selectedKeys && selectedKeys.length) {
        this.form.current.setFieldsValue({
          themeId: pid === 0 ? '' : selectedKeys[0],
        })
      }
    })
  }

  getTreeThemes = () => {
    // 标记每个节点是第几层children
    const signLayerNum = (item, num = 0) => {
      item.layerNum = num
      if (num >= 5) {
        item.disabled = true
      }
      if (item.children) {
        item.children.map((child) => {
          const tempNum = num + 1
          signLayerNum(child, tempNum)
        })
      }
    }
    treeThemes().then(
      (res) => {
        const arr = getNavTreeDataFunc(res)
        // 给tree的数据标上第几层children
        arr.map((item) => {
          signLayerNum(item)
        })
        this.setState({
          treeData: arr,
        })
      },
      (error) => {
        console.log(error)
      },
    )
  }

  onConfirmTheme = () => {
    this.formTheme.current.validateFields().then(values => {
      if (this.state.themeId) {
        values.themeId = this.state.themeId
        values.pid = this.state.pid
      }
      this.setState({ loading: true })
      saveTheme(values).then(
        (res) => {
          this.setState({
            loading: false,
            visibleTheme: false,
          })
          this.getTreeThemes()
          this.props.getThemeList(this.props.modelType)
        },
        (error) => {
          this.setState({ loading: false })
          console.log(error)
        },
      )
    })
  }

  render() {
    const {
      visible, data, titleStr, loading, showLifeCycleNum, tableType, treeData, visibleTheme,
    } = this.state
    const {
      modelName, options, treeOptions, listDataSecret,
    } = this.props
    return (
      <>
        <Modal
          title={`${titleStr}${modelName}`}
          visible={visible}
          width={1020}
          onCancel={this.closeModal}
          maskClosable={false}
          onOk={this.onConfirm}
          okButtonProps={{
            loading,
          }}
        >
          <Spin spinning={loading}>
            <div className={styles.sub_title}>
              <span className={styles.sub_title_txt}>
                模型定义
              </span>
            </div>
            <Form
              ref={this.form}
              labelCol={{ span: 6 }}
              wrapperCol={{ span: 18 }}
              autoComplete="off"
            >
              <Row gutter={100}>
                <Col span={12}>
                  <Item
                    label="模型中文名"
                    name="cnName"
                    rules={[
                      { required: true, message: '请输入模型中文名' },
                      {
                        pattern: new RegExp(regExp.name(2, 32).reg, 'g'),
                        message: regExp.name(2, 32).text,
                      },
                    ]}
                  >
                    <Input
                      placeholder="请输入模型中文名"
                    />
                  </Item>
                </Col>
                <Col span={12}>
                  <Item
                    label="模型英文名"
                    name="enName"
                    rules={[
                      { required: true, message: '请输入模型英文名' },
                    ]}
                  >
                    <Input.Group compact>
                      <Item
                        name={['enName', 'pre']}
                        noStyle
                        rules={[{ required: true, message: '请输入模型英文名' }]}
                        initialValue={options[0]}
                      >
                        <Select style={{ width: '35%' }}>
                          {
                            options.map(item => (
                              <Option value={item} key={item}>{item}</Option>
                            ))
                          }
                        </Select>
                      </Item>
                      <Item
                        name={['enName', 'sec']}
                        noStyle
                        rules={[
                          { required: true, message: '请输入模型英文名' },
                          {
                            pattern: new RegExp(`^[a-zA-Z0-9_\u4e00-\u9fa5]{${5},${128}}$`, 'g'),
                            message: `${5}-${128}个字符，支持中文、英文字母、数字和下划线`,
                          },
                        ]}
                      >
                        <Input style={{ width: '65%' }} placeholder="请输入模型英文名" />
                      </Item>
                    </Input.Group>
                  </Item>
                </Col>
              </Row>
              <Row gutter={100}>
                <Col span={12}>
                  <Item
                    label="主题"
                    name="themeId"
                    rules={[{ required: true, message: '请选择主题' }]}
                  >
                    <TreeSelect
                      dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                      treeData={treeOptions}
                      placeholder="请选择主题"
                      treeDefaultExpandAll
                      dropdownRender={menu => (
                        <>
                          {menu}
                          <Divider style={{ margin: '8px 0' }} />
                          <Space style={{ padding: '0 8px 4px' }}>
                            <Button
                              type="text"
                              icon={<PlusOutlined />}
                              onClick={() => {
                                this.setState({
                                  visibleTheme: true,
                                }, () => {
                                  this.formTheme.current && this.formTheme.current.resetFields()
                                })
                                this.getTreeThemes()
                              }}
                            >
                              新建主题
                            </Button>
                          </Space>
                        </>
                      )}
                    />
                  </Item>
                </Col>
                {
                  showLifeCycleNum ? (
                    <Col
                      span={12}
                    >
                      <Item
                        label="生命周期"
                      >
                        <Input.Group compact>
                          <Item
                            noStyle
                            name="lifeCycle"
                          >
                            <Select
                              placeholder="请选择生命周期"
                              onChange={(value) => {
                                this.setState({ showLifeCycleNum: value === 'all' })
                              }}
                              style={{ width: '50%' }}
                            >
                              <Option value={1} key="1">1天</Option>
                              <Option value={7} key="7">7天</Option>
                              <Option value={30} key="30">30天</Option>
                              <Option value={-1} key="-1">永久</Option>
                              <Option value="all" key="all">自定义</Option>
                            </Select>
                          </Item>
                          <Item
                            rules={[{ required: true, message: '请输入自定义天数' }]}
                            noStyle
                            name="lifeCycleNum"
                          >
                            <InputNumber
                              style={{ width: '50%' }}
                              min={1}
                              placeholder="请输入自定义天数"
                              addonAfter="天"
                            />
                          </Item>
                        </Input.Group>
                      </Item>
                    </Col>
                  ) : (
                    <Col span={12}>
                      <Item
                        label="生命周期"
                        name="lifeCycle"
                        rules={[{ required: true, message: '请选择生命周期' }]}
                      >
                        <Select
                          placeholder="请选择生命周期"
                          onChange={(value) => {
                            this.setState({ showLifeCycleNum: value === 'all' })
                          }}
                        >
                          <Option value={1} key="1">1天</Option>
                          <Option value={7} key="7">7天</Option>
                          <Option value={30} key="30">30天</Option>
                          <Option value={-1} key="-1">永久</Option>
                          <Option value="all" key="all">自定义</Option>
                        </Select>
                      </Item>
                    </Col>
                  )
                }
              </Row>
              {
                this.props.storageType === 'Hive' && (
                  <Row gutter={100}>
                    <Col span={12}>
                      <Item
                        label="是否支持富文本"
                        name="supportRtf"
                        initialValue={false}
                      >
                        <Radio.Group name="radiogroup">
                          <Radio value={false}>否</Radio>
                          <Radio value>是</Radio>
                        </Radio.Group>
                      </Item>
                    </Col>
                  </Row>
                )
              }
              {
                this.props.storageType === 'Sap' && (
                  <Row gutter={100}>
                    <Col span={12}>
                      <Item
                        label="Schema"
                        name="schema"
                        rules={[{ required: true, message: '请选择Schema' }]}
                      >
                        <Select
                          disabled={this.state.modelId !== ''}
                          placeholder="请选择Schema"
                        >
                          {
                            this.props.schemasOption.map(item => (
                              <Option value={item} key={item}>{item}</Option>
                            ))
                          }
                        </Select>
                      </Item>
                    </Col>
                  </Row>
                )
              }
              {/* <Row gutter={100}>
                <Col span={12}>
                  <Item
                    label="数据密级"
                    name="dataSecretId"
                    rules={[{ required: true, message: '请选择数据密级' }]}
                  >
                    <Select
                      placeholder="请选择数据密级"
                    >
                      {
                        listDataSecret && listDataSecret.map(item => (
                          <Option value={item.id} key={item.id}>{item.secretName}</Option>
                        ))
                      }
                    </Select>
                  </Item>
                </Col>
              </Row> */}
            </Form>
            <div className={styles.sub_title}>
              <span className={styles.sub_title_line} />
              <span className={styles.sub_title_txt}>
                属性配置
              </span>
              {/* <span className={styles.sub_title_gray_txt}>
            <i className="iconfont icon-yiwentishi" />
            拖动表格可以对字段进行排序
          </span> */}
            </div>
            <Form ref={this.tableData} component={false} autoComplete="off">
              <ProTable
                // columns={this.state.columns}
                rowKey="key"
                dataSource={data}
                components={{
                  body: {
                    cell: EditableCell,
                  },
                }}
                columns={this.state.columns.map(col => {
                  if (!col.editable) {
                    return col
                  }
                  return {
                    ...col,
                    onCell: (record) => ({
                      record,
                      inputType: col.inputType,
                      dataIndex: col.dataIndex,
                      title: col.title,
                      editing: this.state.editKey === record.key,
                    }),
                  }
                })}
                showQuickJumper={false}
                showSizeChanger={false}
                pagination={false}
                scroll={{ y: 330 }}
              />
            </Form>
            <div className={styles.add_item}>
              <Button
                type="link"
                onClick={this.onAddClick}
                disabled={tableType === 'VIEW'}
              >
                <i className="iconfont icon-tianjia-1" />
                新增字段
              </Button>
            </div>
          </Spin>
        </Modal>
        <Modal
          title="新增主题"
          visible={visibleTheme}
          width={520}
          onCancel={() => {
            this.setState({ visibleTheme: false })
          }}
          maskClosable={false}
          onOk={this.onConfirmTheme}
          confirmLoading={loading}
        >
          <Form
            ref={this.formTheme}
            labelCol={{ span: 5 }}
            wrapperCol={{ span: 19 }}
            autoComplete="off"
          >
            <Item
              label="名称"
              name="themeName"
              rules={[
                { required: true, message: '请输入名称' },
                {
                  pattern: new RegExp(nameReg.reg, 'g'),
                  message: nameReg.text,
                },
              ]}
            >
              <Input placeholder="请输入名称" />
            </Item>
            <Item
              label="主题"
              name="pid"
              rules={[{ required: true, message: '请选择主题' }]}
            >
              <TreeSelect
                showSearch
                getPopupContainer={(triggerNode) => triggerNode.parentNode}
                dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                treeData={treeData}
                placeholder="请选择主题"
                treeDefaultExpandAll
                filterTreeNode={(input, treeNode) => treeNode.title.toLowerCase().indexOf(input.toLowerCase()) >= 0}
              />
            </Item>
            <Item
              label="描述"
              name="themeDesc"
            >
              <TextArea
                placeholder="请输入描述"
                rows={3}
              />
            </Item>
          </Form>
        </Modal>
      </>
    )
  }
}
